package org.hit.burkun.extract;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import org.hit.burkun.db.DBHelper;
import org.hit.burkun.entities.Entity;
import org.hit.burkun.entities.realtions.BaseRealtion;
import org.hit.burkun.extract.FiledsToRealtionMapper.FILED;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
 * 不需要匹配umls id，不过需要进行index_term的转换
 */
public class SqlLinkExtracter extends RelationExtracter {
	private static Logger logger = LoggerFactory
			.getLogger(SqlLinkExtracter.class);
	private DBHelper dbh;
	private FiledsToEntityMapper ent1mapper;
	private FiledsToEntityMapper ent2mapper;
	private FiledsToRealtionMapper realtionmapper;
	private Map<String, DbIDAndDbName> cacheMap;
	private boolean isDone;
	// 使用 limit
	private int curConter = 0;
	// 默认一次取多少条
	protected int defualtBatchNum = 200;

	/**
	 * 构造函数
	 * 
	 * @param dbh
	 *            查询数据的帮助类
	 * @param entity1
	 *            entity1的Mapper
	 * @param entity2
	 *            entity2的Mapper
	 * @param realtion
	 *            关系的mapper
	 * @param cacheMap
	 *            DBID 到 index_term 中的DBID的映射
	 */
	public SqlLinkExtracter(DBHelper dbh, FiledsToEntityMapper entity1,
			FiledsToEntityMapper entity2, FiledsToRealtionMapper realtion,
			Map<String, DbIDAndDbName> cacheMap) {
		this.dbh = dbh.clone(); // 获取clone的属性
		this.ent1mapper = entity1;
		this.ent2mapper = entity2;
		this.realtionmapper = realtion;
		this.cacheMap = cacheMap;
	}

	public SqlLinkExtracter(DBHelper dbh, FiledsToEntityMapper entity,
			FiledsToRealtionMapper realtion, Map<String, DbIDAndDbName> cacheMap) {
		this(dbh, entity, entity, realtion, cacheMap);
	}

	@Override
	public void bengin() {
		logger.debug("connect to db...");
		this.dbh.connectionDB();
		isDone = false;
	}

	@Override
	public void end() {
		logger.debug("disconnect to db...");
		this.dbh.disconnection();
	}

	public boolean isDone() {
		return isDone;
	}

	@Override
	public Collection<BaseRealtion> getNextBatchRealtions(int num) {
		logger.debug("get next " + num + " batch...");
		Collection<BaseRealtion> returnres = new LinkedList<>();
		if (!isDone) {
			String queryStrTemp = realtionmapper.getQueryTemplete()
					+ " limit %d, %d";
			int ient1 = realtionmapper.getResultIdxByFiled(FILED.ENT1);
			int ient2 = realtionmapper.getResultIdxByFiled(FILED.ENT2);
			int iscore = realtionmapper.getResultIdxByFiled(FILED.SCORE);
			int idbid = realtionmapper.getResultIdxByFiled(FILED.DBID);
			int idesc = realtionmapper.getResultIdxByFiled(FILED.DESC);
			int icalcmethod = realtionmapper
					.getResultIdxByFiled(FILED.CALC_METHOD);
			int iother = realtionmapper.getResultIdxByFiled(FILED.OTHER);

			int ievidenceUrl = realtionmapper
					.getResultIdxByFiled(FILED.EVIDENCE_URLS);
			// 使用limit来限定查找的个数
			String queryWithData = String.format(queryStrTemp, curConter, num);

			// System.out.println(queryWithData);

			Collection<String[]> res = dbh.queryData(queryWithData,
					realtionmapper.getFiledsSize());

			// 再次遍历
			for (String[] line : res) {
				String id1 = line[ient1];
				String id2 = line[ient2];
				String score = iscore != -1 ? line[iscore] : null;
				String dbid = idbid != -1 ? line[idbid] : null;
				String desc = idesc != -1 ? line[idesc] : null;
				String calcmethod = icalcmethod != -1 ? line[icalcmethod]
						: null;
				String evidenceUrls = ievidenceUrl != -1 ? line[ievidenceUrl]
						: null;
				String otherData = iother != -1 ? line[iother] : null;
				// 默认设置XREF的值为0.9
				if (calcmethod != null && calcmethod.equals("XREF")) {
					score = "0.9";
				}
				// 假设mapping过去的id是多个（默认用逗号分割）那么需要先split一下
				String[] id1s = id1.split(",");
				String[] id2s = id2.split(",");
				for (String id1i : id1s) {
					for (String id2i : id2s) {
						if (cacheMap.containsKey(id1i)
								&& cacheMap.containsKey(id2i)) {
							// 只保存包含在index_term中的，初始化一堆假term
							DbIDAndDbName en1 = cacheMap.get(id1i);
							DbIDAndDbName en2 = cacheMap.get(id2i);
							Entity entity1 = new Entity(en1.id, en1.dbName,
									null, en1.dbid, ent1mapper.getType());
							Entity entity2 = new Entity(en2.id, en2.dbName,
									null, en2.dbid, ent2mapper.getType());
							BaseRealtion brel = new BaseRealtion(entity1,
									entity2, realtionmapper.isDirect(),
									realtionmapper.getType());
							brel.setCalcMethod(calcmethod);
							if (score != null) {
								brel.setConfidscore(Double.parseDouble(score));
							} else {
								brel.setConfidscore(null);
							}
							brel.setDbid(dbid);
							brel.setDesc(desc);
							brel.setEvidenceUrls(evidenceUrls);
							brel.setOtherData(otherData);
							returnres.add(brel);
						} else {
							logger.debug("can not find " + id1i + "," + id2i
									+ " in the map table!");
						}
					}
				}

			}
			if (res.size() < num) {
				// 取完了
				isDone = true;
			}
			curConter += num;
		}
		return returnres;
	}

	public static class DbIDAndDbName {
		public String dbid;
		public String dbName;
		public String id;

		public DbIDAndDbName(String id, String dbid, String dbName) {
			this.dbid = dbid;
			this.id = id;
			this.dbName = dbName;
		}
	}

	// 获取index_term的map
	public static Map<String, DbIDAndDbName> getMapedData() {
		return getMapedData("select primary_id, db_id, ent_name from index_term");
	}

	public static Map<String, DbIDAndDbName> getMapedData(String sqlStr) {
		DBHelper dbh = DBHelper.getServerData();
		dbh.connectionDB();
		Map<String, DbIDAndDbName> map = new HashMap<String, DbIDAndDbName>();
		Collection<String[]> res = dbh.queryData(sqlStr, 3);
		for (String[] line : res) {
			map.put(line[1], new DbIDAndDbName(line[0], line[1], line[2]));
		}
		dbh.disconnection();
		return map;
	}
}
